package cn.gzy.util;

import cn.gzy.exception.TokenErrorException;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

@Slf4j
public class JWTUtil {
    // 密钥和算法应该移至配置文件或环境变量以提高安全性
    private static final String SECURITY_KEY = "dfdhkhgjdfsfndfbgdfhdf"; // 请替换为更安全的密钥
    private static final String ALGORITHM = "HS256";

    /**
     * 创建 JWT 令牌
     *
     * @param userId 用户 ID
     * @return 生成的 JWT 字符串
     */
    public static String createToken(Integer userId) {
        log.info("Creating JWT for user ID: {}", userId);
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        long expMillis = nowMillis + 15 * 60 * 1000; // 15分钟后过期
        Date expiresAt = new Date(expMillis);

        return JWT.create()
                .withIssuedAt(now) // 当前时间为签发时间
                .withExpiresAt(expiresAt) // 15分钟后过期
                .withClaim("userId", userId.toString()) // 将用户ID转换为字符串存储
                .sign(Algorithm.HMAC256(SECURITY_KEY));
    }

    /**
     * 验证 JWT 令牌
     *
     * @param token JWT 字符串
     * @return 验证后的 JWT 声明信息
     * @throws TokenErrorException 如果 JWT 验证失败，则抛出异常
     */
    public static DecodedJWT verifyToken(String token) throws TokenErrorException {
        log.info("Verifying JWT: {}", token);
        JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECURITY_KEY)).build();
        try {
            DecodedJWT jwt = verifier.verify(token);
            log.info("JWT verified successfully, claims: {}", jwt.getClaims());
            return jwt;
        } catch (Exception e) {
            log.error("JWT verification failed: {}", e.getMessage());
            log.error("Token content (first few characters): {}", token.substring(0, Math.min(token.length(), 50)));
            throw new TokenErrorException("JWT verification failed");
        }
    }

    /**
     * 从 JWT 中提取用户 ID
     *
     * @param token JWT 字符串
     * @return 用户 ID
     * @throws TokenErrorException 如果 JWT 验证失败或用户 ID 声明不存在，则抛出异常
     */
    public static int getUserId(String token) throws TokenErrorException {
        DecodedJWT jwt = verifyToken(token);
        String userIdStr = jwt.getClaim("userId").asString(); // 从JWT中获取userId字符串
        try {
            int userId = Integer.parseInt(userIdStr); // 将字符串转换为整数
            log.info("Extracted user ID from JWT: {}", userId);
            return userId;
        } catch (NumberFormatException e) {
            log.error("User ID claim is not a valid integer in JWT, found: {}", userIdStr);
            throw new TokenErrorException("User ID claim is invalid");
        }
    }
}